<template>
    <div
        style="height: 36px; background-color: #23262e; white-space: nowrap"
        @click.prevent="(e) => onClickTick(e)"
    >
        <div class="i-scale-head-container">
            <template v-for="(item, index) in configArray" :key="item.key">
                <div class="ruler-container" :style="_style(index)">
                    <div v-if="_mark(index)" class="ruler-text">{{ index + 1 }}</div>
                    <span :class="{ 'ruler-scale': true, bold: _mark(index) }"></span>
                    <span :style="_style1(index)" class="loaded"></span>
                </div>
            </template>
        </div>
    </div>
    <div :style="{ left: iState.dragDomLeft + 'px' }" ref="indicatorRef" class="i-scale-indicator">
        <span class="i-scale-indicator-bar"></span>
    </div>
</template>
<script lang="ts" setup>
    import { onMounted, reactive, watch, ref, computed, onUnmounted, Ref } from 'vue';
    import { useInjectEditor } from '../../state';
    const editor = useInjectEditor();
    // interface & type & constant -------------------------------------
    const defaultConfig = {
        spanWidth: 20,
        interval: 5,
        animation: 1,
        emptyColor: '#C5C8CD',
        loadedColor: '#7acae8',
        activeColor: '#fcecc4',
    };

    interface Frame {
        id: number | string;
        resultExist?: boolean | string;
        hasAnnotate?: boolean;
        loadState: boolean | string;
    }

    interface frameProps {
        frames: Array<Frame>;
        status: Array<boolean>;
        config: {
            curFrameIndex: number;
            disabled?: boolean;
            //--
            activeColor?: string;
            emptyColor?: string;
            loadedColor?: string;
            interval?: number;
            spanWidth?: number;
            showProcess?: boolean; // 结果
        };
    }

    // emit & props -------------------------------------
    // const emit = defineEmits(['frameIndexChange']);

    const props = defineProps<frameProps>();

    const indicatorRef = ref<HTMLElement>();

    let parentElement: HTMLElement; // ref<HTMLElement | undefined>(undefined);
    const iState = reactive({
        containerWidth: 0,
        dragDomLeft: 0,
        isDrag: false,
    });

    // life

    onMounted(() => {
        addDragListener();
        addResizeListener();
        setTimeout(domResize, 2000);
    });

    onUnmounted(() => {
        removeEvent();
    });

    // data && computed && watch

    const _config = computed(() => {
        return Object.assign(defaultConfig, props.config || {});
    });

    const configArray = computed(() => {
        const headConfig = [];
        const width = _config.value.spanWidth;
        let temp = 0;
        const maxWidth = Math.max(width * props.frames.length, iState.containerWidth);
        while (temp + width <= maxWidth) {
            headConfig.push({
                key: temp,
            });
            temp += width;
        }
        return headConfig;
    });

    watch(
        () => props.config.curFrameIndex,
        (newValue, oldValue) => {
            checkPosition();
            checkView();
        },
        { immediate: true },
    );

    watch(
        () => props.config.spanWidth,
        () => {
            checkPosition();
        },
    );
    // methods
    const _mark = (index: number) => {
        return (index + 1) % _config.value.interval === 0 || index === 0;
    };

    function addResizeListener() {
        if (indicatorRef.value) {
            parentElement = (indicatorRef.value as HTMLElement).parentElement as any;
            if (!parentElement) return;
            if (!iState.containerWidth) {
                iState.containerWidth = parentElement.offsetWidth;
            }
            window.addEventListener('resize', domResize);
        }
    }

    function domResize() {
        if (parentElement) {
            const dom = parentElement as HTMLElement;
            iState.containerWidth = dom.offsetWidth;
        }
    }

    function removeEvent() {
        if (parentElement) {
            (parentElement as HTMLElement).onmousedown = null;
        }
        if (indicatorRef.value) {
            (indicatorRef.value as HTMLElement).onmousedown = null;
        }
        window.removeEventListener('resize', domResize);
    }

    function checkPosition() {
        const width = _config.value.spanWidth;
        iState.dragDomLeft = props.config.curFrameIndex * width - width / 2 - 2;
    }

    // 校验 将指示器移动滚动到可视范围内
    function checkView() {
        if (parentElement) {
            const container = parentElement as HTMLElement;
            const width = _config.value.spanWidth;
            const needWidth = props.config.curFrameIndex * width;
            const scrollX = container.scrollLeft;
            const total = container.offsetWidth;
            const offset = width;
            if (scrollX + total < needWidth + offset) {
                container.scrollLeft = needWidth - total + offset;
            } else if (scrollX > needWidth - width - offset) {
                container.scrollLeft = needWidth - width - offset;
            }
        }
    }
    const _style1 = (index: number) => {
        const style: Partial<Record<keyof CSSStyleDeclaration, any>> = {
            backgroundColor: 'transparent',
        };
        const item = props.frames[index] as any;
        if (item) {
            switch (item.loadState) {
                case true:
                case 'complete':
                    style.backgroundColor = '#2B3452';
                    break;
                case 'err':
                case 'error':
                case false:
                    style.backgroundColor = '#ff0000';
                    break;
                default:
                    // style.backgroundColor = 'transparent';
                    break;
            }
        }
        return style;
    };
    // 时间轴
    const _style = (index: number) => {
        const item: any = props.frames[index] || {};
        const { loadedColor, emptyColor } = _config.value;
        const style: Partial<Record<keyof CSSStyleDeclaration, any>> = {
            width: _config.value.spanWidth + 'px',
            // backgroundColor: emptyColor,
        };
        if (item.isSample) {
            const itemPre: any = props.frames[index - 1];
            const itemNext: any = props.frames[index + 1];
            const border = '1px solid #e2e3a7';
            style.borderTop = border;
            style.borderBottom = border;
            if (!itemPre?.isSample) {
                style.borderLeft = border;
            }
            if (!itemNext?.isSample) {
                style.borderRight = border;
            }
        }
        return style;
    };
    function preMouseEvent(e: MouseEvent) {
        e.stopPropagation && e.stopPropagation();
        e.preventDefault && e.preventDefault();
        e.cancelBubble = true;
    }

    function getFrameIndexByEvent(event: MouseEvent): number {
        const frameIndex = Math.ceil(event.offsetX / _config.value.spanWidth);
        return frameIndex;
    }

    function onClickTick(event: MouseEvent) {
        const index = getFrameIndexByEvent(event);
        onChangeFrameIndex(index);
    }

    function onChangeFrameIndex(index: number) {
        const beforeIndex = editor.state.frameIndex + 1;
        if (index > props.frames.length) {
            index = props.frames.length;
            return false;
        }
        editor.loadFrame(index - 1); // emit('frameIndexChange', index);
        // editor.reportManager.reportChangeFrame('Time Line', beforeIndex);
        return true;
    }
    function addDragListener() {
        if (indicatorRef.value) {
            const dom = indicatorRef.value as HTMLElement;
            let divX: number;
            let maxX: number;
            let tempDragDomLeft: number;
            const onMouseMove = (e: MouseEvent) => {
                const x = e.clientX - divX;
                preMouseEvent(e);
                divX = e.clientX;
                const tempX = iState.dragDomLeft + x;
                if (tempX <= maxX && tempX > 0) {
                    iState.dragDomLeft += x;
                }
            };
            const onMouseUp = () => {
                document.removeEventListener('mousemove', onMouseMove);
                document.removeEventListener('mouseup', onMouseUp);
                if (iState.isDrag) {
                    iState.isDrag = false;
                    const width = _config.value.spanWidth;
                    const index = Math.ceil(iState.dragDomLeft / width);
                    if (index === props.config.curFrameIndex) {
                        iState.dragDomLeft = tempDragDomLeft;
                    } else {
                        onChangeFrameIndex(index);
                    }
                }
            };
            dom.onmousedown = function (e) {
                e = e || window.event;
                preMouseEvent(e);
                if (e.button === 2) return;
                tempDragDomLeft = iState.dragDomLeft;
                iState.isDrag = true;
                divX = e.clientX;
                const width = _config.value.spanWidth;
                maxX = width * props.frames.length;
                document.addEventListener('mousemove', onMouseMove);
                document.addEventListener('mouseup', onMouseUp);
            };
        }
    }
</script>
<style lang="less">
    .i-scale-indicator {
        // background: aquamarine;
        position: absolute;
        top: 6px;
        bottom: 0;
        z-index: 7;
        width: 4px;
        pointer-events: none;

        &::after {
            position: absolute;
            top: 6px;
            left: 50%;
            width: 1px;
            height: 100%;
            background-color: #ffffff;
            content: '';
            transform: translateX(-50%);
        }

        .i-scale-indicator-bar {
            display: block;
            position: absolute;
            top: 1px;
            left: 50%;
            z-index: 3;
            width: 16px;
            height: 18px;
            background-position: center;
            background-repeat: no-repeat;
            background-size: 100% 100%;
            pointer-events: auto;
            transform: translateX(-50%);
            background-image: url('');
            cursor: grab;
        }

        .disabled {
            cursor: not-allowed;
        }

        .active {
            cursor: grab;
        }

        // .i-tool-scale-head:hover {
        //     background: #89d1f8;
        // }

        .i-tool-scale-body {
            display: block;
            position: absolute;
            top: 6px;
            bottom: 0;
            left: 50%;
            width: 1px;
            border-left: 1px solid #1296db;
            transform: translateX(-50%);
        }
    }

    .i-scale-head-container {
        display: inline-block;
        overflow: hidden;
        height: 100%;
        cursor: pointer;

        .ruler-container {
            display: inline-block;
            position: relative;
            height: 100%;
            background-color: #23262e;
            // background-color: #292746;
            pointer-events: none;
            user-select: none;

            &.active {
                background-color: #1d3f64;
            }

            .ruler-text {
                position: absolute;
                bottom: 0;
                z-index: 4;
                width: 100%;
                font-size: 12px;
                font-family: sans-serif;
                text-align: center;
                color: #aaaaaa;
                line-height: 36px;
                pointer-events: none;
            }

            .loaded {
                position: absolute;
                right: 0;
                bottom: 0;
                left: 0;
                z-index: 0;
                height: 100%;
                box-shadow: inset 0 -1px 0 #43454b;
            }

            .ruler-scale {
                position: absolute;
                bottom: 0;
                left: 50%;
                z-index: 1;
                width: 1px;
                height: 6px;
                border-left: 1px solid #666666;
                transform: translateX(-0.5px);
            }

            .bold {
                border-width: 1px;
                border-color: #cecfd5;
                height: 10px;
            }
        }
    }
    // }
</style>
